package com.jl.card.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import com.jl.util.HexUtil;

public class CAPInfo {
	public static final int ID_HEADER = 1;
	public static final int ID_DIRECTORY = 2;
	public static final int ID_APPLET = 3;
	public static final int ID_IMPORT = 4;
	public static final int ID_CONSTANTPOOL = 5;
	public static final int ID_CLASS = 6;
	public static final int ID_METHOD = 7;
	public static final int ID_STATICFIELD = 8;
	public static final int ID_REFERENCELOCATION = 9;
	public static final int ID_EXPORT = 10;
	public static final int ID_DESCRIPTOR = 11;
	public static final int ID_DEBUG = 12;
	private static String[] COMP_NAMES = { null, "HEADER", "DIRECTORY",
			"APPLET", "IMPORT", "CONSTANTPOOL", "CLASS", "METHOD",
			"STATICFIELD", "REFERENCELOCATION", "EXPORT", "DESCRIPTOR", "DEBUG" };
	private static final String FN_HEADER = "Header.cap";
	private static final String FN_DIRECTORY = "Directory.cap";
	private static final String FN_APPLET = "Applet.cap";
	private static final String FN_IMPORT = "Import.cap";
	private static final String FN_CLASS = "Class.cap";
	private static final String FN_METHOD = "Method.cap";
	private static final String FN_STATICFIELD = "Staticfield.cap";
	private static final String FN_EXPORT = "Export.cap";
	private static final String FN_CONSTANTPOOL = "Constantpool.cap";
	private static final String FN_REFERENCELOCATION = "RefLocation.cap";
	private static final String FN_DESCRIPTOR = "Descriptor.cap";
	private static final String FN_DEBUG = "Debug.cap";
	public String Package_Name = "";
	public byte[] Package_AID = null;
	public int CAP_Major_Version = 2;
	public int CAP_Minor_Version = 1;
	public boolean Support_Integer = false;
	public boolean Has_Applet = false;
	public boolean Has_Export = false;
	public int Package_Major_Version = 1;
	public int Package_Minor_Version = 0;
	public int Size_Class = 0;
	public int Size_Method = 0;
	public int Size_Export = 0;
	public int Size_CAP = 0;
	public int Size_Static = 0;
	public int Size_StaticField = 0;
	public int Size_ConstantPool = 0;
	public int Size_ReferenceLocation = 0;
	public int Size_Descriptor = 0;
	public int Size_Debug = 0;
	public byte[][] Import_List = null;
	public byte[][] Applet_List = null;
	private byte[] raw_Header = null;
	private byte[] raw_Directory = null;
	private byte[] raw_Applet = null;
	private byte[] raw_Import = null;
	private byte[] raw_ConstantPool = null;
	private byte[] raw_Class = null;
	private byte[] raw_Method = null;
	private byte[] raw_StaticField = null;
	private byte[] raw_ReferenceLocation = null;
	private byte[] raw_Export = null;
	private byte[] raw_Descriptor = null;
	private byte[] raw_Debug = null;
	private byte[] dup_Header = null;
	private byte[] dup_Directory = null;
	private byte[] dup_Applet = null;
	private byte[] dup_Import = null;
	private byte[] dup_ConstantPool = null;
	private byte[] dup_Class = null;
	private byte[] dup_Method = null;
	private byte[] dup_StaticField = null;
	private byte[] dup_ReferenceLocation = null;
	private byte[] dup_Export = null;
	private byte[] dup_Descriptor = null;
	private byte[] dup_Debug = null;
	private static byte[] _buf = new byte[65536];
	private static String[] arrayOfString;

	public String getDescription(String paramString) {
		String str = "";
		str = str + paramString + "CAP Version:      " + this.CAP_Major_Version
				+ "." + this.CAP_Minor_Version + "\r\n";
		str = str + paramString + "Package Name:     " + this.Package_Name
				+ "\r\n";
		str = str + paramString + "Package AID:      "
				+ HexUtil.toHexString(this.Package_AID) + "\r\n";
		str = str + paramString + "Package Ver:      "
				+ this.Package_Major_Version + "." + this.Package_Minor_Version
				+ "\r\n";
		str = str + paramString + "Interger:         "
				+ (this.Support_Integer ? "Supported" : "Unsupport") + "\r\n";
		str = str + paramString
				+ (this.Has_Applet ? "Applet Package" : "Library Package")
				+ "\r\n";
		str = str + paramString + "Class Component:  " + dh(this.Size_Class)
				+ " bytes" + "\r\n";
		str = str + paramString + "Method Component: " + dh(this.Size_Method)
				+ " bytes" + "\r\n";
		str = str + paramString + "Export Component: " + dh(this.Size_Export)
				+ " bytes" + "\r\n";
		str = str + paramString + "CAP Loaded Size:  " + dh(this.Size_CAP)
				+ " bytes" + "\r\n";
		str = str + paramString + "Static Image:     " + dh(this.Size_Static)
				+ " bytes" + "\r\n";
		str = str + paramString + "\r\n";
		str = str + paramString + "StaticField Component:       "
				+ dh(this.Size_StaticField) + " bytes" + "\r\n";
		str = str + paramString + "ReferenceLocation Component: "
				+ dh(this.Size_ReferenceLocation) + " bytes" + "\r\n";
		str = str + paramString + "Descriptor Component:        "
				+ dh(this.Size_Descriptor) + " bytes" + "\r\n";
		str = str + paramString + "Debug Component:             "
				+ dh(this.Size_Debug) + " bytes" + "\r\n";
		int i;
		if (this.Import_List != null)
			for (i = 0; i < this.Import_List.length; i++)
				str = str
						+ paramString
						+ "  Import PKG: "
						+ i
						+ ". "
						+ HexUtil.toHexString(this.Import_List[i], 3,
								this.Import_List[i][2] & 0xFF) + " v"
						+ this.Import_List[i][1] + "." + this.Import_List[i][0]
						+ "\r\n";
		if (this.Applet_List != null)
			for (i = 0; i < this.Applet_List.length; i++)
				str = str
						+ paramString
						+ " Applet Info: "
						+ i
						+ ". "
						+ HexUtil.toHexString(this.Applet_List[i], 1,
								this.Applet_List[i][0] & 0xFF)
						+ " install method offset:"
						+ HexUtil.toHex(HexUtil.makeShort(this.Applet_List[i],
								1 + this.Applet_List[i][0] & 0xFF), 2) + "\r\n";
		return str;
	}

	private static boolean readComponent(InputStream paramInputStream,
			int paramInt) throws Exception {
		int i = 0;
		int j = 0;
		while (paramInt > 0) {
			j = paramInputStream.read(_buf, i, paramInt);
			if (j < 0)
				return false;
			i += j;
			paramInt -= j;
		}
		return true;
	}

	public CAPInfo(String paramString1, String paramString2) throws Exception {
		String str = "";
		this.Package_Name = paramString2;
		Enumeration localEnumeration = null;
		ZipFile localZipFile = new ZipFile(paramString1);
		InputStream localInputStream = null;
		localEnumeration = localZipFile.entries();
		ZipEntry localZipEntry = null;
		while (localEnumeration.hasMoreElements()) {
			localZipEntry = null;
			localZipEntry = (ZipEntry) localEnumeration.nextElement();
			localInputStream = localZipFile.getInputStream(localZipEntry);
			str = localZipEntry.getName();
			str = str.substring(str.lastIndexOf("/") + 1);
			int i = (int) localZipEntry.getSize();
			int j;
			int k;
			if (str.equalsIgnoreCase("Header.cap")) {
				readComponent(localInputStream, i);
				this.CAP_Minor_Version = (_buf[7] & 0xFF);
				this.CAP_Major_Version = (_buf[8] & 0xFF);
				j = _buf[9] & 0xFF;
				this.Package_Minor_Version = (_buf[10] & 0xFF);
				this.Package_Major_Version = (_buf[11] & 0xFF);
				k = _buf[12] & 0xFF;
				this.Package_AID = copy(_buf, 13, k);
				if (13 + k < i)
					this.Package_Name = new String(_buf, 13 + k + 1,
							_buf[(13 + k)] & 0xFF);
				this.Support_Integer = ((j & 0x1) != 0);
				this.Has_Export = ((j & 0x2) != 0);
				this.Has_Applet = ((j & 0x4) != 0);
			} else if (str.equalsIgnoreCase("Directory.cap")) {
				readComponent(localInputStream, i);

				this.Size_ConstantPool = (HexUtil.makeShort(_buf, 7) & 0xFFFF);
				this.Size_Class = (HexUtil.makeShort(_buf, 13) & 0xFFFF);
				this.Size_Method = (HexUtil.makeShort(_buf, 15) & 0xFFFF);
				this.Size_StaticField = (HexUtil.makeShort(_buf, 17) & 0xFFFF);
				this.Size_ReferenceLocation = (HexUtil.makeShort(_buf, 19) & 0xFFFF);
				this.Size_Export = (HexUtil.makeShort(_buf, 21) & 0xFFFF);
				this.Size_Descriptor = (HexUtil.makeShort(_buf, 23) & 0xFFFF);
				this.Size_Debug = (HexUtil.makeShort(_buf, 25) & 0xFFFF);
				this.Size_Static = (HexUtil.makeShort(_buf, 27) & 0xFFFF);
			} else if (str.equalsIgnoreCase("Applet.cap")) {
				readComponent(localInputStream, i);
				j = 4;
				this.Applet_List = new byte[_buf[3] & 0xFF][];
				for (k = 0; k < this.Applet_List.length; k++) {
					this.Applet_List[k] = copy(_buf, j,
							(_buf[j] & 0xFF) + 1 + 2);
					j += this.Applet_List[k].length;
				}
			} else if (str.equalsIgnoreCase("Import.cap")) {
				readComponent(localInputStream, i);
				j = 4;
				this.Import_List = new byte[_buf[3] & 0xFF][];
				for (k = 0; k < this.Import_List.length; k++) {
					this.Import_List[k] = copy(_buf, j,
							(_buf[(j + 2)] & 0xFF) + 2 + 1);
					j += this.Import_List[k].length;
				}
			} else if (!readComponent(localInputStream, i)) {
				localInputStream.close();
				throw new Exception("Error reading cap file.");
			}
			byte[] arrayOfByte = copy(_buf, 0, i);
			if (str.equalsIgnoreCase("Header.cap")) {
				this.raw_Header = arrayOfByte;
				this.dup_Header = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("Directory.cap")) {
				this.raw_Directory = arrayOfByte;
				this.dup_Directory = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("Import.cap")) {
				this.raw_Import = arrayOfByte;
				this.dup_Import = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("Applet.cap")) {
				this.raw_Applet = arrayOfByte;
				this.dup_Applet = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("Class.cap")) {
				this.raw_Class = arrayOfByte;
				this.dup_Class = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("Method.cap")) {
				this.raw_Method = arrayOfByte;
				this.dup_Method = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("Staticfield.cap")) {
				this.raw_StaticField = arrayOfByte;
				this.dup_StaticField = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("Export.cap")) {
				this.raw_Export = arrayOfByte;
				this.dup_Export = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("Constantpool.cap")) {
				this.raw_ConstantPool = arrayOfByte;
				this.dup_ConstantPool = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("RefLocation.cap")) {
				this.raw_ReferenceLocation = arrayOfByte;
				this.dup_ReferenceLocation = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("Descriptor.cap")) {
				this.raw_Descriptor = arrayOfByte;
				this.dup_Descriptor = copy(arrayOfByte, 0, i);
			} else if (str.equalsIgnoreCase("Debug.cap")) {
				this.raw_Debug = arrayOfByte;
				this.dup_Debug = copy(arrayOfByte, 0, i);
			} else if (!str.equalsIgnoreCase("MANIFEST.MF")) {
				localInputStream.close();
				throw new Exception("Illegal Component Name [" + str
						+ "] in cap file:\"" + paramString1 + "\"");
			}
		}
		this.Size_CAP = (this.Size_Class + this.Size_Method + this.Size_Export + (this.Has_Export ? 0
				: 1));
		localInputStream.close();
		localZipFile.close();
	}

	public byte[] getRawData(int paramInt) {
		byte[] arrayOfByte1;
		byte[] arrayOfByte2;
		switch (paramInt) {
		case 1:
			arrayOfByte1 = this.raw_Header;
			arrayOfByte2 = this.dup_Header;
			break;
		case 2:
			arrayOfByte1 = this.raw_Directory;
			arrayOfByte2 = this.dup_Directory;
			break;
		case 4:
			arrayOfByte1 = this.raw_Import;
			arrayOfByte2 = this.dup_Import;
			break;
		case 3:
			arrayOfByte1 = this.raw_Applet;
			arrayOfByte2 = this.dup_Applet;
			break;
		case 6:
			arrayOfByte1 = this.raw_Class;
			arrayOfByte2 = this.dup_Class;
			break;
		case 7:
			arrayOfByte1 = this.raw_Method;
			arrayOfByte2 = this.dup_Method;
			break;
		case 8:
			arrayOfByte1 = this.raw_StaticField;
			arrayOfByte2 = this.dup_StaticField;
			break;
		case 10:
			arrayOfByte1 = this.raw_Export;
			arrayOfByte2 = this.dup_Export;
			break;
		case 5:
			arrayOfByte1 = this.raw_ConstantPool;
			arrayOfByte2 = this.dup_ConstantPool;
			break;
		case 9:
			arrayOfByte1 = this.raw_ReferenceLocation;
			arrayOfByte2 = this.dup_ReferenceLocation;
			break;
		case 11:
			arrayOfByte1 = this.raw_Descriptor;
			arrayOfByte2 = this.dup_Descriptor;
			break;
		case 12:
			arrayOfByte1 = this.raw_Debug;
			arrayOfByte2 = this.dup_Debug;
			break;
		default:
			return null;
		}
		if (arrayOfByte1 == null)
			return null;
		System.arraycopy(arrayOfByte1, 0, arrayOfByte2, 0, arrayOfByte1.length);
		return arrayOfByte2;
	}

	private static String[] toPara(String paramString1, String paramString2) {
		Vector localVector = new Vector();
		while (true) {
			arrayOfString = getFirstPara(paramString1, paramString2);
			localVector.addElement(arrayOfString[0]);
			if (arrayOfString[1] == null)
				break;
			paramString1 = arrayOfString[1];
		}
		String[] arrayOfString = new String[localVector.size()];
		for (int i = 0; i < arrayOfString.length; i++)
			arrayOfString[i] = ((String) localVector.elementAt(i));
		return arrayOfString;
	}

	public static void main(String[] paramArrayOfString) {
		BufferedReader localBufferedReader = new BufferedReader(
				new InputStreamReader(System.in));
		CAPInfo localCAPInfo = null;
		Object localObject = null;
		String str1 = "";
		while (true) {
			if (localCAPInfo == null)
				str1 = "";
			System.out.print(str1 + ">");
			String str2;
			try {
				str2 = localBufferedReader.readLine().trim();
			} catch (Exception localException1) {
				localException1.printStackTrace();
				return;
			}
			String[] arrayOfString = toPara(str2, " ");
			if ((arrayOfString[0].equalsIgnoreCase("X"))
					|| (arrayOfString[0].equalsIgnoreCase("EXIT")))
				return;
			if ((arrayOfString[0].equalsIgnoreCase("?"))
					|| (arrayOfString[0].equalsIgnoreCase("H"))
					|| (arrayOfString[0].equalsIgnoreCase("HELP"))) {
				System.out.println("====================");
				System.out.println(" Supported Commands ");
				System.out.println("====================");
				System.out.println("H, HELP      : Show this screen.");
				System.out.println("L, LOAD <cap>: Load CAP file. L 123.cap");
				System.out.println("D, DESC      : Show cap information.");
				System.out.println("M, MESG      : Show last error message.");
				System.out
						.println("R, READ <id> : Read component data of component, id can be 1-12 or partial name of component. R 2, READ HEAD");
				System.out.println("X, EXIT      : Exit to program.");
				System.out.println("====================");
			} else if ((arrayOfString[0].equalsIgnoreCase("M"))
					|| (arrayOfString[0].equalsIgnoreCase("MESG"))) {
				if (localObject == null) {
					System.out.println("No error.");
				} else {
					System.out.println("======= Error =======");
					((Throwable) localObject).printStackTrace();
					System.out.println("=====================");
				}
			} else if ((arrayOfString[0].equalsIgnoreCase("L"))
					|| (arrayOfString[0].equalsIgnoreCase("LOAD"))) {
				if (arrayOfString.length != 2) {
					System.out.println("Command format error!");
					System.out
							.println("L, LOAD <cap>: Load CAP file. L 123.cap");
				} else {
					try {
						localCAPInfo = new CAPInfo(arrayOfString[1],
								arrayOfString[1]);
						str1 = "|" + arrayOfString[1] + " |-";
						System.out.println("CAP file is loaded: \""
								+ localCAPInfo.Package_Name + "\"");
					} catch (Exception localException2) {
						localObject = localException2;
						System.out.println("Error loading CAP file \""
								+ arrayOfString[1] + "\":");
						System.out.println(localException2.getMessage());
						localCAPInfo = null;
					}
					continue;
				}
			} else if ((arrayOfString[0].equalsIgnoreCase("D"))
					|| (arrayOfString[0].equalsIgnoreCase("DESC"))) {
				if (localCAPInfo == null) {
					System.out.println("No CAP file loaded.");
				} else {
					System.out.println("====================");
					System.out.println("   CAP Information  ");
					System.out.println("====================");
					try {
						System.out.println(localCAPInfo.getDescription("  "));
					} catch (Exception localException3) {
						localObject = localException3;
						System.out.println("Error parsing CAP file:");
						System.out.println(localException3.getMessage());
					}
					continue;
				}
			} else if ((arrayOfString[0].equalsIgnoreCase("R"))
					|| (arrayOfString[0].equalsIgnoreCase("READ"))) {
				if (localCAPInfo == null) {
					System.out.println("No CAP file loaded.");
				} else if (arrayOfString.length != 2) {
					System.out.println("Command format error!");
					System.out
							.println("R, READ <id> : Read component data of component, id can be 1-12 or partial name of component. R 2, READ HEAD");
				} else {
					int i = -1;
					String str3 = null;
					int j = 0;
					try {
						i = Integer.parseInt(arrayOfString[1]);
					} catch (Exception localException4) {
						str3 = arrayOfString[1].toUpperCase();
						j = 1;
					}
					while (j < COMP_NAMES.length) {
						if (COMP_NAMES[j].startsWith(str3)) {
							i = j;
							break;
						}
						j++;
					}
					if ((i < 1) || (i > 12)) {
						System.out.println("Command format error!");
						System.out
								.println("R, READ <id> : Read component data of component, id can be 1-12 or partial name of component. R 2, READ HEAD");
					} else {
						str3 = COMP_NAMES[i];
						System.out
								.println("==============================================");
						byte[] arrayOfByte = localCAPInfo.getRawData(i);
						System.out.println(" " + str3 + " Component ("
								+ arrayOfByte.length + " bytes)");
						// System.out
						// .println(ByteProc.toHexBlock(arrayOfByte, 16));
						System.out
								.println("==============================================");
					}
				}
			} else {
				System.out.println("== Unsupported Command ==");
			}
		}
	}

	private static byte[] copy(byte[] paramArrayOfByte, int paramInt1,
			int paramInt2) {
		byte[] arrayOfByte = new byte[paramInt2];
		System.arraycopy(paramArrayOfByte, paramInt1, arrayOfByte, 0, paramInt2);
		return arrayOfByte;
	}

	private static String dh(int paramInt) {
		return "" + paramInt + "(" + HexUtil.toHex((short) paramInt, 2) + ")";
	}

	private static String[] getFirstPara(String paramString1,
			String paramString2) {
		int i = paramString2.length();
		paramString1 = paramString1.trim();
		String[] arrayOfString = new String[2];
		if (paramString1.startsWith(paramString2)) {
			arrayOfString[0] = "";
			arrayOfString[1] = paramString1.substring(i).trim();
		} else {
			int j;
			if (paramString1.startsWith("\"")) {
				j = paramString1.substring(1).indexOf("\"");
				arrayOfString[0] = paramString1.substring(1, j);
				arrayOfString[1] = paramString1.substring(j + 1).trim();
			} else {
				j = paramString1.indexOf(paramString2);
				if (j < 0) {
					arrayOfString[0] = paramString1;
				} else {
					arrayOfString[0] = paramString1.substring(0, j).trim();
					arrayOfString[1] = paramString1.substring(j + i).trim();
				}
			}
		}
		return arrayOfString;
	}
}
